package com.newx.test.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Desc TODO
 * @Date 2025/1/16 11:31
 * @Created by yxl
 */
@Configuration
@EnableScheduling
public class Socket8080Config {

    public static final ConcurrentHashMap<String, Socket> clientMap = new ConcurrentHashMap<>();

    private static final ExecutorService threadPool = Executors.newFixedThreadPool(1);

    public static final int BUFFER_SIZE = 1024; // 增大缓冲区大小以提高传输效率
    public static final int TIMEOUT_MS = 5000;  // 确认超时时间（毫秒）

    @PostConstruct
    public void startMCUServer() {
        String host = "192.168.0.33"; // 本地回环地址
        int port = 5000;
        //String host = "124.223.6.164"; // 本地回环地址
        //int port = 39001; // 监听端口

        new Thread(() -> {
            try (ServerSocket serverSocket = new ServerSocket(port)) {
                System.out.println("Java服务端正在监听 " + host + ":" + port + "...");

                while (true) {
                    Socket clientSocket = serverSocket.accept();
                    System.out.println("收到客户端连接请求");

                    // 使用线程池处理每个客户端连接
                    threadPool.submit(() -> handleClient(clientSocket));
                }
            } catch (IOException e) {
                System.err.println("无法绑定到端口: " + e.getMessage());
            } finally {
                threadPool.shutdown();
            }
        }).start();
    }

    private void handleClient(Socket clientSocket) {
        try {
            // 设置读取超时
            //clientSocket.setSoTimeout(TIMEOUT_MS);

            try (
                    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                    DataOutputStream outStream = new DataOutputStream(clientSocket.getOutputStream())
            ) {
                System.out.println("处理来自 " + clientSocket.getInetAddress() + " 的连接");

                // 等待客户端发送消息
                String deviceId;
                while ((deviceId = in.readLine()) != null) {
                    System.out.println("收到客户端消息: " + deviceId);
                    if(deviceId ==null || deviceId.isEmpty()){
                        System.out.println("Invalid device ID");
                        continue;
                    }
                    clientMap.put(deviceId, clientSocket);

                    // 根据接收到的消息准备发送文件
//                    if ("Request file".equalsIgnoreCase(deviceId)) {
//                        System.out.println("等待用户确认发送文件...");
//
//                        // 直接发送文件
//                        //sendFile(outStream, in, "F:\\Desktop\\test.bin");
//                        //sendFile(outStream, in, "/www/wwwroot/test.bin");
//                        break;
//                    } else {
//                        outStream.writeUTF("Unknown command");
//                        outStream.flush();
//                    }
                }
            }
        } catch (SocketTimeoutException e) {
            System.err.println("客户端连接超时: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("处理客户端时发生IO异常: " + e.getMessage());
        }
    }

    private void sendFile(DataOutputStream outStream, BufferedReader in, String filePath) throws IOException {
        Path path = Paths.get(filePath);
        if (!Files.exists(path)) {
            outStream.writeUTF("File not found: " + filePath);
            outStream.flush();
            return;
        }

        File file = path.toFile();
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytesRead;

            // 发送文件名和文件大小
            outStream.writeUTF(file.getName());
            outStream.writeLong(file.length());
            outStream.flush();

            // 发送文件内容，分包处理
            int packetNumber = 0;
            while ((bytesRead = fis.read(buffer)) != -1) {
                // 发送数据包
                outStream.writeInt(packetNumber); // 数据包序号
                outStream.writeInt(bytesRead);    // 数据长度
                outStream.write(buffer, 0, bytesRead);
                outStream.flush();

                // 等待确认
                long startTime = System.currentTimeMillis();
                boolean ackReceived = false;
                while (!ackReceived && (System.currentTimeMillis() - startTime < TIMEOUT_MS)) {
                    String ack = in.readLine();
                    if (ack != null && ack.equals("ACK " + packetNumber)) {
                        ackReceived = true;
                        System.out.println("收到确认，继续发送下一个数据包 " + packetNumber);
                        break;
                    }
                }

                if (!ackReceived) {
                    System.out.println("未收到确认，重传数据包 " + packetNumber);
                    fis.getChannel().position(fis.getChannel().position() - bytesRead);
                    continue;
                }

                packetNumber++;
            }

            System.out.println("文件发送完成: " + filePath);
        }
    }

    // 推送消息给指定设备ID的客户端
    public static void pushMessageToClient(String deviceId, String message) {
        Socket clientSocket = clientMap.get(deviceId);
        if (clientSocket != null && !clientSocket.isClosed()) {
            try {
                OutputStream out = clientSocket.getOutputStream();
                String msg = "发送消息：" + deviceId + "=" + message;
                out.write(msg.getBytes());
                out.flush();
                System.out.println("Message sent to " + deviceId);
            } catch (IOException e) {
                e.printStackTrace();
                clientMap.remove(deviceId);  // 移除断开连接的客户端
            }finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        } else {
            System.out.println("Client " + deviceId + " not found or disconnected.");
        }
    }
}
